#ifndef __ROM_H
#define __ROM_H


#define DEE_ADDR	0xF000
#define PFL_ADDR	0x0000
#define PFL_LST_ADDR	0x0FFF

#define RfDfuAddr					0xE000
#define PrfClrTxRxPtrAddr	0xE30D
#define PrfSetIdleAddr		0xE325
#define Crc16Addr					0xE33D
#define PeeRdAddr					0xE374
#define PeeWrAddr					0xE3AB
#define DeeWrAddr					0xE3D7
#define DeeRdAddr					0xE405
#define RamFillAddr				0xE41B
#define RamCpyAddr				0xE42B
#define RamCmpAddr				0xE43C
#define Div16Addr					0xE45B
#define Mul16Addr					0xE4D1
#define ChkSumAddr				0xE4FE
#define PrfWrRegPtrAddr		0xE57C
#define PrfRdRegPtrAddr		0xE5C9
#define PrfInitAddr				0xE618


#define TkInitAddr				0xF800
#define RefMaxminAddr			0xF970
#define TdcNorDatAddr			0xFDD0
#define TdcSlpDatAddr			0xFDF0
#define LMulDivAddr				0xFF20


#define RX(ram) *(uint8_t*)(ram)
#define LCALL(addr) (*((void(*)(void))addr))()
	
#define RX0  0xFF
#define RX1  0xFE
#define RX2  0xFD
#define RX3  0xFC
#define RX4  0xFB
#define RX5  0xFA
#define RX6  0xF9
#define RX7  0xF8
#define RX8  0xF7
#define RX9  0xF6

#ifdef USE_ROM_CODE
#define Rom_RfDfu(){\
	LCALL(RfDfuAddr);\
}

#define Rom_PrfClrTxRxPtr(){\
	LCALL(PrfClrTxRxPtrAddr);\
}

#define Rom_PrfSetIdle(){\
	LCALL(PrfSetIdleAddr);\
}

#define Rom_Crc16(addr, dat_ptr, len){\
	RX(RX0) = (uint8_t)addr;\
	RX(RX1) = (uint8_t)dat_ptr;\
	RX(RX2) = len;\
	LCALL(Crc16Addr);\
}

#define Rom_PflRd(pee_addr,dat_ptr,len){\
	RX(RX0)=(uint8_t)(pee_addr>>8);\
	RX(RX1)=(uint8_t)pee_addr;\
	RX(RX2)=(uint8_t)dat_ptr;\
	RX(RX3)=len;\
	LCALL(PeeRdAddr);\
}

#define Rom_PflWr(pee_addr,dat_ptr,len){\
	RX(RX0)=(uint8_t)(pee_addr>>8);\
	RX(RX1)=(uint8_t)pee_addr;\
	RX(RX2)=(uint8_t)dat_ptr;\
	RX(RX3)=len;\
	LCALL(PeeWrAddr);\
}

#define Rom_DeeWr(dee_addr,dat_ptr,len){\
	RX(RX0)=(uint8_t)(dee_addr>>8);\
	RX(RX1)=(uint8_t)dee_addr;\
	RX(RX2)=(uint8_t)dat_ptr;\
	RX(RX3)=len;\
	LCALL(DeeWrAddr);\
}

#define Rom_DeeRd(dee_addr,dat_ptr,len){\
	RX(RX0)=(uint8_t)(dee_addr>>8);\
	RX(RX1)=(uint8_t)dee_addr;\
	RX(RX2)=(uint8_t)dat_ptr;\
	RX(RX3)=len;\
	LCALL(DeeRdAddr);\
}

#define Rom_RamFill(des_addr, dat, len){\
	RX(RX0) = (uint8_t)des_addr;\
	RX(RX1) = dat;\
	RX(RX2) = len;\
	LCALL(RamFillAddr);\
}

#define Rom_RamCpy(des_addr, src_addr, len){\
	RX(RX0) = (uint8_t)des_addr;\
	RX(RX1) = (uint8_t)src_addr;\
	RX(RX2) = len;\
	LCALL(RamCpyAddr);\
}

#define Rom_RamCmp(des_addr, src_addr, len, res_addr){\
	RX(RX0) = (uint8_t)des_addr;\
	RX(RX1) = (uint8_t)src_addr;\
	RX(RX2) = len;\
	RX(RX3) = (uint8_t)res_addr;\
	LCALL(RamCmpAddr);\
}

#define Rom_Div16(div_addr, dived_addr, res_addr){\
	RX(RX0) = (uint8_t)div_addr;\
	RX(RX1) = (uint8_t)dived_addr;\
	RX(RX2) = (uint8_t)res_addr;\
	LCALL(Div16Addr);\
}

#define Rom_Mul16(mul_addr, muled_addr, res_addr){\
	RX(RX0) = (uint8_t)mul_addr;\
	RX(RX1) = (uint8_t)muled_addr;\
	RX(RX2) = (uint8_t)res_addr;\
	LCALL(Mul16Addr);\
}

#define Rom_ChkSum(addr, len, res_addr){\
	RX(RX0) = (uint8_t)addr;\
	RX(RX1) = len;\
	RX(RX2) = (uint8_t)res_addr;\
	LCALL(ChkSumAddr);\
}

#define Rom_PrfWrRegPtr(fq, reg, dat_addr, len){\
	RX(RX0) = fq;\
	RX(RX1) = reg;\
	RX(RX2) = (uint8_t)dat_addr;\
	RX(RX3) = len;\
	LCALL(PrfWrRegPtrAddr);\
}

#define Rom_PrfRdRegPtr(fq, reg_addr, dat_ptr, len){\
	RX(RX0) = fq;\
	RX(RX1) = (reg_addr|PRF_REG_RD);\
	RX(RX2) = (uint8_t)dat_ptr;\
	RX(RX3) = len;\
	LCALL(PrfRdRegPtrAddr);\
}

#define Rom_PrfInit(fq, res_addr){\
	P1M0 &= ~(BIT4|BIT6);\
	RX(RX0) = fq;\
	RX(RX1) = (uint8_t)res_addr;\
	LCALL(PrfInitAddr);\
}
#endif	//USE_ROM_CODE

#define Rom_TkInit(chH, chL){\
	RX(RX1) = chL;\
	RX(RX2) = chH;\
	LCALL(TkInitAddr);\
}


#ifndef USE_ROM_CODE
void PflRd(uint16_t addr, uint8_t *dat, uint8_t len);
#endif	//USE_ROM_CODE

#endif	//__ROM_H
